package com.iflysse.services.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.iflysse.common.ActivityState;
import com.iflysse.common.ResultEnum;
import com.iflysse.dao.QuestionDao;
import com.iflysse.dao.TeacherDao;
import com.iflysse.dao.TeachingClassDao;
import com.iflysse.dao.TestDao;
import com.iflysse.pojo.bo.CommonBoResp;
import com.iflysse.pojo.bo.req.*;
import com.iflysse.pojo.bo.resp.*;
import com.iflysse.pojo.po.common.CommonPoResp;
import com.iflysse.pojo.po.req.AnswerQuestionDetailPoReq;
import com.iflysse.pojo.po.req.TestStatePoReq;
import com.iflysse.pojo.po.resp.*;
import com.iflysse.services.TestService;
import com.iflysse.util.CommonUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.sql.SQLException;
import java.util.*;

@Service
public class TestServiceImpl implements TestService {

    @Autowired
    TeachingClassDao teachingClassDao;
    @Autowired
    TestDao testDao;
    @Autowired
    TeacherDao teacherDao;
    @Autowired
    QuestionDao questionDao;


    /**
     * 根据学生编号获取当前学生的课后作业(测试)
     *
     * @param studentIdBoReq
     * @return
     */
    @Override
    public TeachingActivityListBoResp getTestByStudentId(StudentIdBoReq studentIdBoReq) throws SQLException {
        TeachingActivityListBoResp teachingActivityListBoResp = new TeachingActivityListBoResp();
        //获取当前学生的所有班级编号
        List<String> teachingClass = teachingClassDao.getTeachingClassIdsByStudentId(studentIdBoReq.getStudentId());
        List<String> teachingClassIds = teachingClassDao.getTeachingClassIdsByStudentId2(teachingClass);
        if(teachingClassIds.size()>0) {

            //根据班级编号获取测试列表
            List<TeachingActivityPoResp> testByTeachingClassIds = testDao.getTestByTeachingClassIds(teachingClassIds, studentIdBoReq.getStudentId());

            testByTeachingClassIds.forEach(teachingActivityPoResp -> {
                TeachingActivityBoResp teachingActivityBoResp = CommonUtil.objToObj(teachingActivityPoResp, TeachingActivityBoResp.class);
                try {
                    int studentAmount = teachingClassDao.getStudentAmountByTeachingClassId(teachingActivityPoResp.getTeachingClassId());
                    int pecent = (int)((teachingActivityBoResp.getCompletedPercentage()*1.0 / studentAmount)*100);
                    teachingActivityBoResp.setCompletedPercentage(pecent);
                } catch (SQLException sqlException) {

                    sqlException.printStackTrace();
                }


                teachingActivityBoResp.setStudentState(teachingActivityPoResp.getStudentState());
                //判断测试状态,不等于3,判断是否时间已经过期,过期则改变测试状态为3
                if(teachingActivityPoResp.getState() != 3) {
                    if (teachingActivityPoResp.getExpirationDate().getTime() > new Date().getTime()) {
                        teachingActivityBoResp.setState(ActivityState.STATE_RUNNING);
                    } else {
                        teachingActivityBoResp.setState(ActivityState.STATE_FINISH);
                        //过期则改变测试状态为3
                        TestStatePoReq testStatePoReq = new TestStatePoReq();
                        testStatePoReq.setTestId(teachingActivityBoResp.getActivityId());
                        testStatePoReq.setState(ActivityState.STATE_FINISH);
                        try {
                            testDao.updateTestState(testStatePoReq);
                        } catch (SQLException sqlException) {
                            sqlException.printStackTrace();
                        }
                    }
                }else{
                    teachingActivityBoResp.setState(ActivityState.STATE_FINISH);
                }

                teachingActivityListBoResp.getTeachingActivityList().add(teachingActivityBoResp);
            });
        }

        return teachingActivityListBoResp;
    }

    /**
     * 学生点击某个测试进去的数据业务
     * 根据学生学号和测试编号,查询测试详情
     *
     * @param studentIdAndTaskIdBoReq
     * @return
     */
    @Override
    public StudentTestStateBoResp getStudentTestAndStateByTestIdAndStudentId(StudentIdAndTaskIdBoReq studentIdAndTaskIdBoReq) throws SQLException {
        StudentTestStateBoResp studentTestStateBoResp = new StudentTestStateBoResp();

        //根据测试编号获取测试详情,taskid等同于testid
        TestPoResp test = testDao.getTestByTestId(studentIdAndTaskIdBoReq.getTaskId());
        studentTestStateBoResp = CommonUtil.objToObj(test, StudentTestStateBoResp.class);
        //根据老师编号获取老师姓名
        String teacherName = teacherDao.getTeacherNameByTeacherId(test.getTeacherId());
        studentTestStateBoResp.setTeacherName(teacherName);
        Integer number = testDao.getNumberOfAnswerTestByTestIdAndStudentId(studentIdAndTaskIdBoReq.getTaskId(), studentIdAndTaskIdBoReq.getStudentId());

        //根据测试编号和当前学生编号获取当前学生本次测试状态
        studentTestStateBoResp.setStudentTestState(number);
        return studentTestStateBoResp;
    }

    /**
     * 当前学生测试答题页面下面的每次测试记录
     *
     * @param studentIdAndTaskIdBoReq
     * @return
     */
    @Override
    public StudentAnswerListBoResp getStudentAnswerListByTestIdAndStudentId(StudentIdAndTaskIdBoReq studentIdAndTaskIdBoReq) throws SQLException {

        List<StudentAnswerRecordPoResp> recordOfTestList = testDao.getRecordOfTestByTestIdAndStudentId(studentIdAndTaskIdBoReq.getTaskId(), studentIdAndTaskIdBoReq.getStudentId());

        StudentAnswerListBoResp studentAnswerListBoResp = new StudentAnswerListBoResp();

        recordOfTestList.forEach(studentAnswerRecordPoResp -> {
            StudentAnswerRecordBoResp studentAnswerRecordBoResp= CommonUtil.objToObj(studentAnswerRecordPoResp, StudentAnswerRecordBoResp.class);
            studentAnswerListBoResp.getStudentAnswerRecordList().add(studentAnswerRecordBoResp);
        });

        return studentAnswerListBoResp;
    }

    /**
     * 学生点击开始(继续)答题,进入答题界面
     * 显示标题,答题卡
     *
     * @param studentIdAndTaskIdBoReq
     * @return
     */
    @Transactional
    @Override
    public StudentAnswerBoResp startToAnswerByTestIdAndStudentId(StudentIdAndTaskIdBoReq studentIdAndTaskIdBoReq) throws SQLException {

        //判断当前学生本次测试是否存在未完成测试,
        String studentTestId = testDao.getUnfinishedTestIdByStudentId(studentIdAndTaskIdBoReq.getStudentId(),studentIdAndTaskIdBoReq.getTaskId());
        //没有未完成的测试,创建一个新测试记录
        if(studentTestId == null) {
            //添加一条学生答题记录,student_test_id
            studentTestId = UUID.randomUUID().toString();
            CommonPoResp commonPoResp=new CommonPoResp();
            int i = testDao.addStudentTest(studentTestId, studentIdAndTaskIdBoReq.getTaskId(), studentIdAndTaskIdBoReq.getStudentId());
            CommonUtil.printToPoResult(commonPoResp,1);
        }


        //查询本次测试的信息
        TestPoResp testPoResp = testDao.getTestByTestId(studentIdAndTaskIdBoReq.getTaskId());
        //构建返回值
        StudentAnswerBoResp studentAnswerBoResp = CommonUtil.objToObj(testPoResp, StudentAnswerBoResp.class);
        //设置本次学生测试的编号
        studentAnswerBoResp.setStudentTestId(studentTestId);

        //判断本次考试是否已经存在数据,
        List<AnswerSheetPoResp> answerSheetPoRespList = testDao.getQuestionList4StudentTest(studentTestId);
        // 如果存在,即从数据库中直接获取本次考试的题目编号及答案
        // 如果不存在,获取本次测试的所有题目id,判断题目是否乱序,生成题目顺序,并插入到数据库中
        if(answerSheetPoRespList.size() == 0){
            //获取本次测试的题目编号列表
            List<String> questionIdList = testDao.getQuestionList4StudentTestByTestId(studentIdAndTaskIdBoReq.getTaskId());
            if(testPoResp.isSubjectOrder()){
                //问题乱序
                Collections.shuffle(questionIdList);
            }
            //传入dao的参数,封装了详情的编号和问题编号
            List<AnswerQuestionDetailPoReq> answerQuestionDetailPoReqs = new ArrayList<>();
            questionIdList.forEach(qid->{
                //封装存入数据库的数据
                AnswerQuestionDetailPoReq answerQuestionDetailPoReq = new AnswerQuestionDetailPoReq();
                answerQuestionDetailPoReq.setQuestionId(qid);
                answerQuestionDetailPoReq.setStudentTestDetailId(UUID.randomUUID().toString());
                answerQuestionDetailPoReqs.add(answerQuestionDetailPoReq);
                
                //封装返回前端的数据
                AnswerSheetPoResp answerSheetPoResp = new AnswerSheetPoResp();
                answerSheetPoResp.setStudentTestDetailId(answerQuestionDetailPoReq.getStudentTestDetailId());
                answerSheetPoResp.setQuestionId(qid);
                //将数据添加到返回集合
                answerSheetPoRespList.add(answerSheetPoResp);
                

                try {
                    //根据问题编号获取问题标准答案
                    QuestionPoResp questionByQuestionId = questionDao.getQuestionByQuestionId(qid);
                    JSONObject jsonObject = JSON.parseObject(questionByQuestionId.getQuestionContent());
                    String correctAnswer = jsonObject.getString("correct");
                    answerQuestionDetailPoReq.setStandardAnswer(correctAnswer);
                } catch (SQLException sqlException) {
                    sqlException.printStackTrace();
                }
            });
            CommonPoResp addDetailResp=new CommonPoResp();
            //将问题生成答题记录,后面学生答题,修改该题的选项即可,不需插入
            int i = testDao.addStudentAnswerQuestDetailRecord(answerQuestionDetailPoReqs);
            CommonUtil.printToPoResult(addDetailResp,i);
        }

        List<AnswerSheetBoResp> answerSheetBoRespList = new ArrayList<>();
        //将po转bo
        answerSheetPoRespList.forEach(answerSheetPoResp -> {
            answerSheetBoRespList.add(CommonUtil.objToObj(answerSheetPoResp, AnswerSheetBoResp.class));
        });
        studentAnswerBoResp.setAnswerSheetBoRespList(answerSheetBoRespList);


        return studentAnswerBoResp;
    }




    /**
     * 学生点击选项,实现答题功能
     *
     * @param studentAnswerQuestionBoReq
     * @return
     */
    @Transactional
    @Override
    public CommonBoResp answerQuestionByStudentIdAndStudentTestId(StudentAnswerQuestionBoReq studentAnswerQuestionBoReq) throws SQLException {
        CommonPoResp commonPoResp =new CommonPoResp();
        //根据答题详情编号和答案修改记录,实现答题功能
        int i = testDao.updateAnswerOfTest(studentAnswerQuestionBoReq.getStudentAnswer(), studentAnswerQuestionBoReq.getStudentTestDetailId());
        CommonUtil.printToPoResult(commonPoResp,i);
        return CommonUtil.objToObj(commonPoResp, CommonBoResp.class);
    }

    /**
     * 学生交卷,改变测试的状态:0,进行中,1,已交卷
     *
     * @param studentTestIdBoReq
     * @return
     */
    @Transactional
    @Override
    public CommonBoResp submitTest(StudentTestIdBoReq studentTestIdBoReq) throws SQLException {
        //根据测试编号,查询测试编号和学生编号
        StudentTestPoResp studentTestPoResp = testDao.getStudentTestByStudentTestId(studentTestIdBoReq.getStudentTestId());
        //判断该学生是第几次完成该测试
        Integer number = testDao.getNumberOfAnswerTestByTestIdAndStudentId(studentTestPoResp.getTestId(),studentTestPoResp.getStudentId());
        int updateCode = 0;
        if(number == 1) {
            CommonPoResp updateNumberOfFinishedTest = new CommonPoResp();
                    //更新试卷表的完成人数
            int i = testDao.updateNumberOfFinishedTest(studentTestPoResp.getTestId());
            CommonUtil.printToPoResult(updateNumberOfFinishedTest,i);
            updateCode = updateNumberOfFinishedTest.getCode();
        }
        //计算学生成绩
        //查看本次学生的正确题数
        int rightNumber = testDao.getRightAnswerNumbersByStudentTestId(studentTestIdBoReq.getStudentTestId());
        CommonPoResp updateStudentTestState = new CommonPoResp();
        //更新学生本次考试的状态及正确答题数
        int i = testDao.updateStudentTestState(studentTestIdBoReq.getStudentTestId(), rightNumber);
        CommonUtil.printToPoResult(updateStudentTestState,i);
        int result = 0;
        if(updateCode == ResultEnum.SUCCESS.getCode() && updateStudentTestState.getCode() == ResultEnum.SUCCESS.getCode()){
            result = 1;
        }

        CommonBoResp commonBoResp = new CommonBoResp();
        CommonUtil.printToBoResult(commonBoResp,result);
        return commonBoResp;
    }

    /**
     * 根据学生编号获取该学生的未完成测试
     *
     * @param studentIdBoReq
     * @return
     */
    @Override
    public TestListBoResp getUnfinishedTestByStudentId(StudentIdBoReq studentIdBoReq) throws SQLException {
        TestListBoResp testListBoResp = new TestListBoResp();
        List<String> orderedWatingTaskIdsByTeachingIds = new ArrayList<>();
        TaskListBoResp taskListBoResp = new TaskListBoResp();
        //获取当前学生的所有班级
        List<String> teachingClassIds = teachingClassDao.getTeachingClassIdsByStudentId(studentIdBoReq.getStudentId());
        if(teachingClassIds.size() >0) {
            //根据学生编号获取当前学生已经完成的任务编号列表
            List<String> completeTestIds = testDao.getFinishedTestByStudentId(studentIdBoReq.getStudentId());
            //得到没有学习的任务编号
            List<TestPoResp> testPoRespList = testDao.getUnfinishedTestByTeachingClassIdAndFinishedTestId(teachingClassIds, completeTestIds);
            testPoRespList.forEach(testPoResp -> {
                testListBoResp.getTestList().add(CommonUtil.objToObj(testPoResp, TestBoResp.class));
            });

        }

        return  testListBoResp;

    }

    /**
     * 根据学生编号获取该学生的未完成测试数量
     *
     * @param studentIdBoReq
     * @return
     */
    @Override
    public UnfinishedTestAmountBoResp getUnfinishedTestAmountByStudentId(StudentIdBoReq studentIdBoReq) throws SQLException {
        TestListBoResp testListBoResp = new TestListBoResp();
        List<String> orderedWatingTaskIdsByTeachingIds = new ArrayList<>();
        TaskListBoResp taskListBoResp = new TaskListBoResp();
        //获取当前学生的所有班级
        List<String> teachingClassIds = teachingClassDao.getTeachingClassIdsByStudentId(studentIdBoReq.getStudentId());
        List<String> finalTeachingClassIdList  = teachingClassDao.getTeachingClassIdsByStudentId2(teachingClassIds);
        UnfinishedTestAmountBoResp unfinishedTestAmountBoResp = new UnfinishedTestAmountBoResp();
        if(finalTeachingClassIdList.size() >0) {
            //根据学生编号获取当前学生已经完成的任务编号列表
            List<String> completeTestIds = testDao.getFinishedTestByStudentId(studentIdBoReq.getStudentId());
            //得到没有学习的任务数量
            int amount  = testDao.getUnfinishedTestAmountByTeachingClassIdAndFinishedTestId(finalTeachingClassIdList, completeTestIds);
           unfinishedTestAmountBoResp.setAmount(amount);

        }
        return unfinishedTestAmountBoResp;
    }

    @Override
    public StudentTestDetailBoResp getStudentTestDetailByStudentTestId(StudentTestIdBoReq studentTestIdBoReq) throws SQLException {
        StudentTestDetailBoResp studentTestDetailBoResp = new StudentTestDetailBoResp();
        //根据学生测试编号获取测试编号
        StudentTestPoResp studentTestByStudentTestId = testDao.getStudentTestByStudentTestId(studentTestIdBoReq.getStudentTestId());
        //设置本次测试的信息
        studentTestDetailBoResp.setDoTime(studentTestByStudentTestId.getDoTime());
        studentTestDetailBoResp.setNumberCorrect(studentTestByStudentTestId.getNumberCorrect());
        studentTestDetailBoResp.setTotalNumber(studentTestByStudentTestId.getTotalNumber());
        studentTestDetailBoResp.setTestId(studentTestByStudentTestId.getTestId());
        studentTestDetailBoResp.setStudentId(studentTestByStudentTestId.getStudentId());
        //根据测试编号获取测试详情
        TestPoResp testPo = testDao.getTestByTestId(studentTestByStudentTestId.getTestId());
        studentTestDetailBoResp.setTestTitle(testPo.getTestTitle());//测试标题
        studentTestDetailBoResp.setPublishDate(testPo.getPublishDate());//测试发布时间
        studentTestDetailBoResp.setOptionOrder(testPo.isOptionOrder());//选项是否乱序
        //设置本次测试是否已经到期
        studentTestDetailBoResp.setTestEnd(testPo.getExpirationDate().getTime() >new Date().getTime() );

        //获取本次测试的题目编号及学生答案
        List<AnswerSheetPoResp> answerSheetPoRespList = testDao.getQuestionList4StudentTest(studentTestIdBoReq.getStudentTestId());

        List<AnswerSheetBoResp>answerSheetBoResps=new ArrayList<>();
        answerSheetPoRespList.forEach(answerSheetPoResp -> {
            AnswerSheetBoResp answerSheetBoResp=   CommonUtil.objToObj(answerSheetPoResp,AnswerSheetBoResp.class);
            answerSheetBoResps.add(answerSheetBoResp);
        });
        studentTestDetailBoResp.setAnswerSheetBoRespList(answerSheetBoResps);

        //将问题编号添加到问题编号集合
        List<String> questionIds = new ArrayList<>();
        answerSheetPoRespList.forEach(answerSheetPoResp -> {
            questionIds.add(answerSheetPoResp.getQuestionId());
        });

        //获取问题编号对应的问题列表
        List<QuestionPoResp> questionListByQuestionIds = questionDao.getQuestionListByQuestionIds(questionIds);
        List<QuestionBoResp>questionBoResps=new ArrayList<>();
        questionListByQuestionIds.forEach(questionPoResp -> {
            QuestionBoResp questionBoResp= CommonUtil.objToObj(questionPoResp,QuestionBoResp.class);
            questionBoResps.add(questionBoResp);
        });
        studentTestDetailBoResp.setQuestionContent(questionBoResps);

        return studentTestDetailBoResp;
    }

    @Override
    public StudentTestDetailAnalyseBoResp getStudentTestDetailAnalyseByTestId(TestIdBoReq testIdBoReq) throws SQLException {
        StudentTestDetailAnalyseBoResp studentTestDetailAnalyseBoResp = new StudentTestDetailAnalyseBoResp();

        //获取本次测试的基本信息
        TestPoResp test = testDao.getTestByTestId(testIdBoReq.getTestId());
        studentTestDetailAnalyseBoResp.setTestTitle(test.getTestTitle());
        studentTestDetailAnalyseBoResp.setTestId(test.getTestId());
        String tname = teacherDao.getTeacherNameByTeacherId(test.getTeacherId());
        studentTestDetailAnalyseBoResp.setTeacherName(tname);
        studentTestDetailAnalyseBoResp.setPublishDate(test.getPublishDate());
        studentTestDetailAnalyseBoResp.setExpirationDate(test.getExpirationDate());
        studentTestDetailAnalyseBoResp.setTestState(test.getTestState());
        studentTestDetailAnalyseBoResp.setNumberOfComplete(test.getNumberOfComplete());
        studentTestDetailAnalyseBoResp.setTotalQuestionNumber(test.getTotalQuestionNumber());

        //获取本次测试的总人数
        //通过班级编号获取班级学生人数
        int number = teachingClassDao.getStudentAmountByTeachingClassId(test.getTeachingClassId());
        studentTestDetailAnalyseBoResp.setTotalAmount(number);
        //获取平均正确率和耗时
        Map<String, Object> avgAccuracyAndUseTime = testDao.getAvgAccuracyAndUseTimeByTestId(test.getTestId());
        if(avgAccuracyAndUseTime.get("AvgOfAccuracy")!=null){
            studentTestDetailAnalyseBoResp.setAvgOfAccuracy(Integer.parseInt((avgAccuracyAndUseTime.get("AvgOfAccuracy")).toString()));
        }

        studentTestDetailAnalyseBoResp.setAvgOfUsetime(Integer.parseInt(avgAccuracyAndUseTime.get("AvgOfUseTime").toString()));


        //获取知识点的正确率列表
        List<Map<String, Object>> knowledgePoint = testDao.getKnowledgePointByTestId(test.getTestId());
        KnowledgePointAccuracy knowledgePointAccuracy;
        for(int i =0;i<knowledgePoint.size();i++){
            knowledgePointAccuracy = new KnowledgePointAccuracy();
            knowledgePointAccuracy.setKnowledgePointId(knowledgePoint.get(i).get("knowledge_point_id").toString());
            knowledgePointAccuracy.setKnowledgePointName(knowledgePoint.get(i).get("knowledge_point_name").toString());
            int avgOfAccuracy = testDao.getKnowledgePointAccuracyByTestIdAndKnowledgePointId(test.getTestId(),knowledgePointAccuracy.getKnowledgePointId());
            knowledgePointAccuracy.setAvgOfAccuracy(avgOfAccuracy);
            studentTestDetailAnalyseBoResp.getKnowledgePointAccuracyList().add(knowledgePointAccuracy);


        }

        return studentTestDetailAnalyseBoResp;
    }


}
